//******************************************************************************
//  MSP430G2xx1 Demo - Timer_A, Ultra-Low Pwr UART 9600 Echo, 32kHz ACLK
//
//  Description: Use Timer_A CCR0 hardware output modes and SCCI data latch
//  to implement UART function @ 9600 baud. Software does not directly read and
//  write to RX and TX pins, instead proper use of output modes and SCCI data
//  latch are demonstrated. Use of these hardware features eliminates ISR
//  latency effects as hardware insures that output and input bit latching and
//  timing are perfectly synchronised with Timer_A regardless of other
//  software activity. In the Mainloop the UART function readies the UART to
//  receive one character and waits in LPM3 with all activity interrupt driven.
//  After a character has been received, the UART receive function forces exit
//  from LPM3 in the Mainloop which configures the port pins (P1 & P2) based
//  on the value of the received byte (i.e., if BIT0 is set, turn on P1.0).

//  ACLK = TACLK = LFXT1 = 32768Hz, MCLK = SMCLK = default DCO
//  //* An external watch crystal is required on XIN XOUT for ACLK *//  
//
//               MSP430G2xx1
//            -----------------
//        /|\|              XIN|-
//         | |                 | 32kHz
//         --|RST          XOUT|-
//           |                 |
//           |   CCI0B/TXD/P1.1|-------->
//           |                 | 9600 8N1
//           |   CCI0A/RXD/P1.2|<--------
//
//  D. Dang
//  Texas Instruments Inc.
//  October 2010
//  Built with CCS Version 4.2.0 and IAR Embedded Workbench Version: 5.10
//******************************************************************************

#define GCC430

#ifndef GCC430
	#include "msp430g2231.h"
#else
	// The GCC compiler uses --mcpu="msp430g2231" to automatically select the correct
	// headers.
	#include <io.h>
	#include <signal.h>
#endif

//------------------------------------------------------------------------------
// Hardware-related definitions
//------------------------------------------------------------------------------
#define UART_TXD   0x02                     // TXD on P1.1 (Timer0_A.OUT0)
#define UART_RXD   0x04                     // RXD on P1.2 (Timer0_A.CCI1A)

#define PWM_LEFT   0x08                     // Left Motor on P1.3
#define PWM_RIGHT  0x10                     // Right Motor on P1.4

#define ZERO_VALUE 1300

//------------------------------------------------------------------------------
// Conditions for 9600 Baud SW UART, SMCLK = 1MHz
//------------------------------------------------------------------------------
#define UART_TBIT_DIV_2     (1000000 / (9600 * 2))
#define UART_TBIT           (1000000 / 9600)

//------------------------------------------------------------------------------
// Global variables used for full-duplex UART communication
//------------------------------------------------------------------------------
unsigned short rxBuffer;                     // Received UART character
unsigned short watchdogCount;                 // Tracks number of watchdog interrupts
volatile unsigned short pulsewidth;               // The delay in microseconds to turn off the left pulse
unsigned char rxBytes;

//------------------------------------------------------------------------------
// Function prototypes
//------------------------------------------------------------------------------
void TimerA_UART_init(void);

//------------------------------------------------------------------------------
// main()
//------------------------------------------------------------------------------
void main(void)
{
   	DCOCTL = 0x00;                          // Set DCOCLK to 1MHz
	BCSCTL1 = CALBC1_1MHZ;
	DCOCTL = CALDCO_1MHZ;

	WDTCTL = WDT_MDLY_0_5;               //Change WDT+ to interval timer mode, SMCL source 0.5mS interval
	IE1 |= WDTIE;						//Enable Watchdog interrupt
	watchdogCount = 0;                  // Initialize watchdog timer interrupt count.

    P1OUT = PWM_LEFT;                           // Initialize all GPIO
    P1SEL = UART_RXD;                       // Timer function for TXD/RXD pins
    P1DIR = 0xFF & ~UART_RXD;               // Set all pins but RXD to output
    P2OUT = 0x00;
    P2SEL = 0x00;
    P2DIR = 0xFF;

		rxBytes = 0;
    flipflop = 0;
    leftpulsewidth = rightpulsewidth = 1600;

    __enable_interrupt();
    
    TimerA_UART_init();                     // Start Timer_A UART
    
    for (;;)
    {
        // Wait for incoming character
        __bis_SR_register(LPM0_bits);

	if(flipflop)
	{
		rightpulsewidth = rxBuffer;
	}
	else
	{
		leftpulsewidth = rxBuffer;
	}

	P1OUT ^= 0x1;
    }
}
//------------------------------------------------------------------------------
// Function configures Timer_A for full-duplex UART operation
//------------------------------------------------------------------------------
void TimerA_UART_init(void)
{
    TACCTL0 = CCIE;
    TACCTL1 = SCS + CM1 + CCIE;		      // Sync, Neg Edge, Int
    TACTL = TASSEL_2 + MC_2;                  // SMCLK, start in continuous mode
}

//------------------------------------------------------------------------------
// Watchdog interrupt, sets Pins high on 11th and 1st interrupt
//------------------------------------------------------------------------------
#ifndef GCC430
	#pragma vector=WDT_VECTOR
	__interrupt void watchdog_timer_interrupt (void)
#else
	interrupt(WDT_VECTOR) watchdog_timer_interrupt (void)
#endif
{	
	++watchdogCount;
	if(watchdogCount & 0x3) { //If it is not a multiple of four, just exit
	return;
	}
	else if(watchdogCount == 4 && leftpulsewidth != 0) { //Doesn't matter when it is, as long as it's cyclic
		P1OUT &= PWM_LEFT; // Turn on left pulse
		TACCR0 = TAR + leftpulsewidth; // Set timer to turn off left pulse
		return;            // Shortcut and return from the call
	}
	else if(watchdogCount == 28 && rightpulsewidth != 0) { //Any number greater than 9 works
		P1OUT &= PWM_RIGHT;
		TACCR0 = TAR + rightpulsewidth;
		return;
	}
	else if(watchdogCount == 40) { // 20 ms cycle
		watchdogCount = 0;
	}
	P1OUT &= ~(PWM_LEFT + PWM_RIGHT); // If 2 ms have elapsed, kill the pulse
}

//------------------------------------------------------------------------------
// TIMERA0 interrupt. Turns off pulse
//------------------------------------------------------------------------------
#ifndef GCC430
	#pragma vector=TIMERA0_VECTOR
	__interrupt void pwm_off_interrupt(void)
#else
	interrupt(TIMERA0_VECTOR) pwm_off_interrupt(void)
#endif
{	
	P1OUT &= ~(PWM_LEFT + PWM_RIGHT);        // Turn off PWM pulses
}
    
//------------------------------------------------------------------------------
// Timer_A UART - Receive Interrupt Handler  REPLACE W/ ORIGINAL AJV 06/07/2011
//------------------------------------------------------------------------------
#ifndef GCC430
	#pragma vector = TIMERA1_VECTOR
	__interrupt void  serial_interrupt(void)
#else
	interrupt(TIMERA1_VECTOR) serial_interrupt(void)
#endif
{
	static unsigned char rxBitCnt = 8;
	static unsigned char rxData = 0;

	if(TAIV & TAIV_TACCR1) { // Why use __even_in_range with one option???
		TACCR1 += UART_TBIT;                 // Add Offset to CCRx
		if (TACCTL1 & CAP) {                 // Capture mode = start bit edge
			TACCTL1 &= ~CAP;                 // Switch capture to compare mode
			TACCR1 += UART_TBIT_DIV_2;       // Point CCRx to middle of D0
		}
		else {
			rxData >>= 1;
			if (TACCTL1 & SCCI) {            // Get bit waiting in receive latch
				rxData |= 0x80;
			}
			rxBitCnt--;
			if (rxBitCnt == 0) {             // All bits RXed?
				rxBytes ^= 1;
				P1OUT ^= 1;
				if(rxBytes)
				{
					rxBuffer = rxData;           // Store in global variable
				}
				else
				{
					rxBuffer |= (unsigned short)rxData << 8;
				}
				rxBitCnt = 8;                // Re-load bit counter
				TACCTL1 |= CAP;              // Switch compare to capture mode
				if(!rxBytes)
					__bic_SR_register_on_exit(LPM0_bits);  // Clear LPM0 bits from 0(SR)
			}
		}
	}
}
//------------------------------------------------------------------------------
